#ifndef _LING_SLAB_H_
#define _LING_SLAB_H_

#include <stddef.h>
#include"list.h"

enum slab_move_flag{
    SLAB_MOVE_FLAG_FREE_TO_PARTIAL,
    SLAB_MOVE_FLAG_PARTIAL_TO_FULL,
    SLAB_MOVE_FLAG_FULL_TO_PARTIAL,
    SLAB_MOVE_FLAG_PARTIAL_TO_FREE,
};

struct slab{
    struct list_head slab_list;      //slab所在的链表free/partial/full
    struct kmem_cache *slab_cache;  //结构体用其追踪所有
    void *freelist;                 //用于指向页框中空闲对象链表。空闲对象链表包含页框中每个空闲对象的索引。
    void *s_mem;                    //第一个对象的地址
    unsigned int active;
};

struct kmem_cache_node{
    struct list_head slabs_partial;     //连接着page
    struct list_head slabs_full;        //连接着page
	struct list_head slabs_free;        //连接着page

    unsigned long total_slabs;	    //总的slabs对象
    
	unsigned long free_slabs;	    //slabs_free链表下有多少个slab对象
    unsigned long partial_slabs;    //slabs_partial链表下有多少个slab对象
    unsigned long full_slabs;       //slabs_full链表下有多少个slab对象

	unsigned long free_objects;
	unsigned int free_limit;        //触发回收机制的limit 超过free_limit的slab将会回收 
};

struct kmem_cache{
    //每个CPU可以有一个本地的缓存，然后全局有一个slab   此处忽略每个CPU的缓存

   
    // unsigned int freelist_size;

    unsigned int gfporder;
    void (*ctor)(void *obj);        //创建对象时需要调用的构造函数

    //创建时候的参数
    const char *name;      
    struct list_head list;     //用于全局链接的访问
    int refcount;
    int object_size;                    //对象的size是多大
    unsigned int object_num;                   //表示一个slab上面有几个objs

    int align;

    struct kmem_cache_node node;
};


extern struct list_head slab_caches;
extern struct kmem_cache *kmem_cache;

static struct kmem_cache kmem_cache_boot = {
    .name = "kmem_cache",
    .object_size = sizeof(struct kmem_cache),
    .gfporder = 1,
    .node.free_limit = 1,       
};

void show_slab_info();
void show_slab_node_info(struct kmem_cache *cachep);

void slab_init();
void kmem_cache_init();
//创建和销毁一个kmem_cache
struct kmem_cache *kmem_cache_create(const char *name,unsigned int size,unsigned int align,int flags,void(*ctor)(void *));

void kmem_cache_destory(struct kmem_cache * cachep);
//从kmem_cache对应的slab中分配一个object
void *kmem_cache_alloc(struct kmem_cache *cachep,int flags);

//释放object给原来的slab
void kmem_cache_free(struct kmem_cache* cachep,void* objp);
void kmem_cache_init(struct kmem_cache *cachep);

void slab_test(struct kmem_cache *cachep);
#endif